const cp = require("child_process");
const iconv = require("iconv-lite");
const path = require("path");
const axios = require("axios");
const CommonAxerrHandler = require("./CommonAxerrHandler");
const Toolbox = require("./toolbox");
const fs = require('fs-extra');
const util = require("util");
const tmp_package = require("tmp");
const TreeCli = require("tree-cli/");

/**
 * @returns {Promise<{err_msg:String|null}>}
 * @param {String} full_path 
 */
function del(full_path) {
  return new Promise(resolve => {
    fs.remove(full_path, (err => {
      if (err) {
        return resolve({
          err_msg: err.message
        })
      }
      return resolve({
        err_msg: ""
      })
    }))
  })
}


/**
cp.exec(`rar a poi-233.rar -rr9% -m0 index.js`,{
  encoding:"buffer"
},(err,stdout,stderr)=>{
  debugger
  let strout = iconv.decode(stdout,'gbk');
  let strerr = iconv.decode(stderr,'gbk');
  debugger
})
*/




/**
 * 
 * @param {String[]} inputFiles 
 * @param {String} definedOutputRarFullpath 给定为完整路径,并且带上.rar后缀
 * @param {Number} volumnSizeInMb 
 * @returns {Promise<{ok:Boolean,msg:String,data:{rarfile_realpath:String}}>}
 */
function rarPack(inputFiles, definedOutputRarFullpath, volumnSizeInMb) {
  return new Promise(async resolve => {
    let o_checkedMakedDir = await (
      /**
       * @returns {Promise<{ok:Boolean,msg:String}>}
       */
      function checkMakeDir() {
        let parsed = path.parse(definedOutputRarFullpath);
        return new Promise(r => {
          fs.mkdirp(parsed.dir, (err) => {
            if (err) {
              return r({
                ok: false,
                msg: err.message
              })
            }
            return r({
              ok: true,
              msg: "ok"
            })
          })
        })
      })();
    if (!o_checkedMakedDir.ok) {
      return resolve({
        ok: false,
        msg: `不能创建目标路径的文件夹来安置新建RAR文件(${definedOutputRarFullpath}):${o_checkedMakedDir.msg}`
      })
    }

    tmp_package.tmpName((err, temp_filelist_fullpath) => {
      if (err) {
        return resolve({
          ok: false,
          msg: `无法获得临时文件名来作为input文件列表:${util.inspect(err)}`
        })
      }
      let inputFilesPlusCommentFile = Array.from(inputFiles);
      // inputFilesPlusCommentFile.push(path.join(__dirname, "../static/藤宫武藏@TSDM@LK@KF.txt"))
      fs.writeFile(temp_filelist_fullpath, `\uFEFF${inputFilesPlusCommentFile.map(e => `${e}\n`).join("")}`, (err1) => {
        if (err1) {
          return resolve({
            ok: false,
            msg: `无法写入临时文件:${err1.message}`
          })
        };
        let commentFileForRar = path.join(__dirname, "../static/comment.txt");

        let command = `rar a "${definedOutputRarFullpath}" -y -scfcr -z"${commentFileForRar}"  -ep1 -rr3% -m0 -ma4 -v${volumnSizeInMb}m @"${temp_filelist_fullpath}"`;
        cp.exec(command, {
          encoding: "buffer",
          maxBuffer: Infinity
        }, async (err, stdout, stderr) => {
          let strout = stdout.toString();
          let strerr = stderr.toString();
          // removeTmpCb();
          fs.remove(temp_filelist_fullpath).then(function () { }).catch(_ => { })
          if (err) {
            if (stderr) {
              // return resolve({
              //   ok:false,
              //   msg:`${strerr.trim()}\n${err.message}`
              // })
              return CommonAxerrHandler(resolve)(`${strerr.trim()}\n${err.message}`);
            }
            return resolve({
              ok: false,
              msg: `cp.exec failed : ${err.message}`
            })
          }
          if (strerr) {
            return CommonAxerrHandler(resolve)(strerr.trim());
          }
          /**@description {接下来哦寻找压缩成得到功的RAR文件完整路径}} */
          let parsedDORF = path.parse(definedOutputRarFullpath)
          let dirPath = parsedDORF.dir;
          let o_listDir = await Toolbox.safeListDir(dirPath);
          //首先寻找完全匹配的
          if (o_listDir.map(e => e.full_path).includes(definedOutputRarFullpath)) {
            return resolve({
              ok: true,
              msg: "ok",
              rarfile_realpath: definedOutputRarFullpath
            })
          }
          //然后寻找.part1.rar 或者.part01.rar|.part001.rar等
          let filtered_findpart1 = o_listDir.filter(e => {
            return e.relative_path.startsWith(parsedDORF.name)
              && e.relative_path.search(/\.part0*1\.rar$/) >= 0
          })
          if (!filtered_findpart1.length) {
            return resolve({
              ok: false,
              msg: `can not find .part1 rar file in [${o_listDir.map(e => e.full_path).join(",")}]`
            })
          }
          /**@description 这里姑且认为不会出现同时存在.part1和.part01的情况 */

          // debugger
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              rarfile_realpath: filtered_findpart1[0].full_path
            }
          })

        });

      })
    });
  })
}

/**
 * 
 * @param {String[]} inputFiles 
 * @param {String} definedOutputRarFullpath 给定为完整路径,并且带上.rar后缀
 * @param {Number} volumnSizeInMb 
 * @param {String} password
 * @returns {Promise<{ok:Boolean,msg:String,data:{rarfile_realpath:String}}>}
 */
function rarPackPlusPassword(inputFiles, definedOutputRarFullpath, volumnSizeInMb, password) {
  return new Promise(async resolve => {
    let o_checkedMakedDir = await (
      /**
       * @returns {Promise<{ok:Boolean,msg:String}>}
       */
      function checkMakeDir() {
        let parsed = path.parse(definedOutputRarFullpath);
        return new Promise(r => {
          fs.mkdirp(parsed.dir, (err) => {
            if (err) {
              return r({
                ok: false,
                msg: err.message
              })
            }
            return r({
              ok: true,
              msg: "ok"
            })
          })
        })
      })();
    if (!o_checkedMakedDir.ok) {
      return resolve({
        ok: false,
        msg: `不能创建目标路径的文件夹来安置新建RAR文件(${definedOutputRarFullpath}):${o_checkedMakedDir.msg}`
      })
    }

    tmp_package.tmpName((err, temp_filelist_fullpath) => {
      if (err) {
        return resolve({
          ok: false,
          msg: `无法获得临时文件名来作为input文件列表:${util.inspect(err)}`
        })
      }
      let inputFilesPlusCommentFile = Array.from(inputFiles);
      // inputFilesPlusCommentFile.push(path.join(__dirname, "../static/藤宫武藏@TSDM@LK@KF.txt"))
      fs.writeFile(temp_filelist_fullpath, `\uFEFF${inputFilesPlusCommentFile.map(e => `${e}\n`).join("")}`, (err1) => {
        if (err1) {
          return resolve({
            ok: false,
            msg: `无法写入临时文件:${err1.message}`
          })
        };
        let commentFileForRar = path.join(__dirname, "../static/comment.txt");

        let command = `rar a "${definedOutputRarFullpath}" -y -scfcr -z"${commentFileForRar}"  -ep1 -hp${password} -rr3% -m0 -ma4 -v${volumnSizeInMb}m @"${temp_filelist_fullpath}"`;
        cp.exec(command, {
          encoding: "buffer",
          maxBuffer: Infinity
        }, async (err, stdout, stderr) => {
          let strout = stdout.toString();
          let strerr = stderr.toString();
          // removeTmpCb();
          fs.remove(temp_filelist_fullpath).then(function () { }).catch(_ => { })
          if (err) {
            if (stderr) {
              // return resolve({
              //   ok:false,
              //   msg:`${strerr.trim()}\n${err.message}`
              // })
              return CommonAxerrHandler(resolve)(`${strerr.trim()}\n${err.message}`);
            }
            return resolve({
              ok: false,
              msg: `cp.exec failed : ${err.message}`
            })
          }
          if (strerr) {
            return CommonAxerrHandler(resolve)(strerr.trim());
          }
          /**@description {接下来哦寻找压缩成得到功的RAR文件完整路径}} */
          let parsedDORF = path.parse(definedOutputRarFullpath)
          let dirPath = parsedDORF.dir;
          let o_listDir = await Toolbox.safeListDir(dirPath);
          //首先寻找完全匹配的
          if (o_listDir.map(e => e.full_path).includes(definedOutputRarFullpath)) {
            return resolve({
              ok: true,
              msg: "ok",
              data: {
                rarfile_realpath: definedOutputRarFullpath
              }
            })
          }
          //然后寻找.part1.rar 或者.part01.rar|.part001.rar等
          let filtered_findpart1 = o_listDir.filter(e => {
            return e.relative_path.startsWith(parsedDORF.name)
              && e.relative_path.search(/\.part0*1\.rar$/) >= 0
          })
          if (!filtered_findpart1.length) {
            return resolve({
              ok: false,
              msg: `can not find .part1 rar file in [${o_listDir.map(e => e.full_path).join(",")}]`
            })
          }
          /**@description 这里姑且认为不会出现同时存在.part1和.part01的情况 */

          // debugger
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              rarfile_realpath: filtered_findpart1[0].full_path
            }
          })

        });

      })
    });
  })
}

/**
 * 
 * @param {String} rarfile_fullpath 
 * @param {String} extract_dist_dir 
 * @returns {Promise<{ok:boolean,msg:string}>}
 */
function unrar(rarfile_fullpath, extract_dist_dir) {
  extract_dist_dir = path.resolve(extract_dist_dir) + "/";
  return new Promise(resolve => {
    cp.exec(`rar x -y -scfr -p- "${rarfile_fullpath}" "${extract_dist_dir}"`, {
      // encoding: "buffer",
      maxBuffer: Infinity
    }, (err, stdout, stderr) => {
      // debugger
      let strout = stdout.toString();
      let strerr = stderr.toString();
      if (err) {
        if (stderr) {
          return CommonAxerrHandler(resolve)(`${strerr.trim()}\n${err.message}`);
        }
        return resolve({
          ok: false,
          msg: `cp.exec failed : ${err.message}`
        })
      }
      if (strerr) {
        return CommonAxerrHandler(resolve)(strerr.trim());
      }
      resolve({
        ok: true,
        msg: "ok"
      })

    })
  })
}

/**
 * @returns {Promise<{ok:Boolean,msg:String}>}
 * @param {String} rarfile_fullpath 
 */
function rarTest(rarfile_fullpath) {
  return new Promise(resolve => {
    cp.exec(`rar t "${rarfile_fullpath}"`, {
      encoding: "buffer",
      maxBuffer: Infinity
    }, (err, stdout, stderr) => {
      let strout = iconv.decode(stdout, 'gbk');
      let strerr = iconv.decode(stderr, 'gbk');
      if (err) {
        if (stderr) {
          return CommonAxerrHandler(resolve)(`${strerr.trim()}\n${err.message}`);
        }
        return resolve({
          ok: false,
          msg: `cp.exec failed : ${err.message}`
        })
      }
      if (strerr) {
        return CommonAxerrHandler(resolve)(strerr.trim());
      }

      resolve({
        ok: true,
        msg: "ok"
      })
    })
  })
}

/**
 * @returns {Promise<{ok:Boolean,msg:String}>}
 * @param {String} rarfile_fullpath 
 */
function rarTestPlusPassword(rarfile_fullpath, password) {
  return new Promise(resolve => {
    cp.exec(`rar t "${rarfile_fullpath}" -p${password}`, {
      encoding: "buffer",
      maxBuffer: Infinity
    }, (err, stdout, stderr) => {
      let strout = iconv.decode(stdout, 'gbk');
      let strerr = iconv.decode(stderr, 'gbk');
      if (err) {
        if (stderr) {
          return CommonAxerrHandler(resolve)(`${strerr.trim()}\n${err.message}`);
        }
        return resolve({
          ok: false,
          msg: `cp.exec failed : ${err.message}`
        })
      }
      if (strerr) {
        return CommonAxerrHandler(resolve)(strerr.trim());
      }

      resolve({
        ok: true,
        msg: "ok"
      })
    })
  })
}
/**
 * 
 * @param {String} rarfile_fullpath 
 * @param {String} dist_dir_fullpath 
 * @returns {Promise<{ok:Boolean,msg:String,data:{rar_name:String,involved_files:string[]}}>}
 */
function unpackWith7z(rarfile_fullpath, dist_dir_fullpath) {
  if (!dist_dir_fullpath.endsWith(path.sep)) {
    dist_dir_fullpath = dist_dir_fullpath + path.sep
  }
  return new Promise(async resolve => {
    let parsed_p = path.parse(rarfile_fullpath);
    if (!rarfile_fullpath.endsWith(".rar")) {
      return resolve({
        ok: false,
        msg: `这个函数暂时只打算处理rar后缀的文件(${parsed_p.base})`
      })
    }
    cp.exec(`7z x "${rarfile_fullpath}" -y -p -sccUTF-8 -o"${dist_dir_fullpath}" `, {
      maxBuffer: Infinity
    },
      async (err, stdout, stderr) => {
        if (err) {
          return resolve({
            ok: false,
            msg: err.message.trim()
          })
        }
        if (stderr) {
          return resolve({
            ok: false,
            msg: stderr.trim()
          })
        }
        //找Volumes = 1这一行
        let matched = stdout.match(/Volumes = ([0-9]+)/);
        if (!(matched && matched.length == 2)) {
          return resolve({
            ok: false,
            msg: `无法找到涉及多少卷:${stdout}`
          })
        }
        let files_count = Number(matched[1]);
        if (!files_count) {
          return resolve({
            ok: false,
            msg: `无法找到涉及多少卷:${stdout}`
          })
        }
        if (files_count == 1) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              involved_files: [rarfile_fullpath],
              rar_name: parsed_p.name
            }
          })
        }
        let name_common_part_matched = parsed_p.base.match(/(.*part)[0]*1\.rar/);
        if (!(name_common_part_matched
          && name_common_part_matched.length == 2)) {
          return resolve({
            ok: false,
            msg: `解压成功,但是试图寻找相关的part失败:${parsed_p.base}不能匹配正则'/(.*part)[0]*1\.rar/'`
          })
        }
        let o_list = await Toolbox.safeListDir(parsed_p.dir);
        let listed_filtered = o_list.filter(e => {
          if (e.stats.isFile()) {
            let pathParsed = path.parse(e.full_path);
            if (pathParsed.base.startsWith(name_common_part_matched[1])
              && pathParsed.base.search(/part[0-9]+\.rar$/) >= 0) {
              return true;
            }
          }
          return false;
        })
        if (listed_filtered.length != files_count) {
          return resolve({
            ok: false,
            msg: `解压成功,但是试图寻找相关part时数量不对:
            \n files_count =  ${files_count}
            \n 过滤出啦的文件有${listed_filtered.length}个:${
              listed_filtered.map(e => e.full_path).join(" , ")
              }`
          })
        }
        let rar_name = name_common_part_matched[1].replace(/\.part$/, "");
        if (parsed_p.base.replace(/\.part[0]*1\.rar$/, "") == "") {
          rar_name = ""
        }
        if (parsed_p.base.replace(/part[0]*1\.rar$/, "") == "") {
          rar_name = ""
        }
        resolve({
          ok: true,
          msg: "ok",
          data: {
            involved_files: listed_filtered.map(e => e.full_path),
            rar_name: rar_name
          }
        })
      })
  })
}

/**
 * @returns {Promise<{ok:Boolean,msg:String,data:{list:Array<{Path:String,Size:Number,Folder:Boolean}>}}>}
 * @param {String} rarzipFile_fullpath 
 */
function listWith7z(rarzipFile_fullpath) {
  return new Promise(resolve => {
    cp.exec(`7z l -ba -p -slt -sccUTF-8 "${rarzipFile_fullpath}"`, {}, (err, stdout, stderr) => {
      if (err) {
        return resolve({
          ok: false,
          msg: err.message.trim()
        })
      }
      if (stderr) {
        return resolve({
          ok: false,
          msg: stderr.trim()
        })
      }
      let info_arr = stdout.trim().split("\r\n\r\n");
      /**@type {Array<{Path:String,Size:Number,Folder:Boolean}>} */
      let result_list = [];
      for (let item_string of info_arr) {
        let isFolder = item_string.includes("\nFolder = +\r");
        let matched_path = item_string.match(/Path\s=\s(.+)\r\n/);
        if (!(matched_path && matched_path.length == 2)) {
          return resolve({
            ok: false,
            msg: `can not parse Path from string ${item_string}`
          })
        }
        let matched_size = item_string.match(/\nSize\s=\s([0-9]+)\r\n/);
        if (!(matched_size && matched_size.length == 2)) {
          return resolve({
            ok: false,
            msg: `can not parse Size from string ${item_string}`
          })
        }
        let _path = matched_path[1];
        let _size = Number(matched_size[1]);
        result_list.push({
          Path: _path,
          Size: _size,
          Folder: isFolder
        })
      }
      resolve({
        ok: true,
        msg: "ok",
        data: {
          list: result_list
        }
      })
    })
  })
}

/**
 * @returns {Promise<{ok:Boolean,msg:String,data:{out_file_path:String}}>}
 * @param {String} archive_fullpath 压缩包的路径
 * @param {String} filePath_in_arc 包里面的文件Path,根据listWith7z得到
 * @param {String} dist_dir 试图解压出来文件夹的目录:这个目录可以是不存在的,7z会试图建立
 */
function extractOneFileWith7z(archive_fullpath, filePath_in_arc, dist_dir) {
  return new Promise(resolve => {
    cp.exec(`7z e "${archive_fullpath}" -y -sccUTF-8 -o"${dist_dir}" -- "${filePath_in_arc}" `,
      async (err, stdout, stderr) => {
        if (err) {
          if (err) {
            return resolve({
              ok: false,
              msg: err.message.trim()
            })
          }
          if (stderr) {
            return resolve({
              ok: false,
              msg: stderr.trim()
            })
          }
        }
        let outfp = path.join(dist_dir, path.basename(filePath_in_arc));
        let oexist = await Toolbox.checkExist(outfp);
        if (!oexist) {
          return resolve({
            ok: false,
            msg: `不存在解压出来的文件=${outfp}`
          })
        }
        resolve({
          ok: true,
          msg: "ok",
          data: {
            out_file_path: outfp
          }
        })
      })
  })

}


/**
 * @param {String} subject
 * @param {String} info_html 
 * @param {string} log_webhook_url
 */
function logToWebhook(subject, info_html, log_webhook_url) {
  console.log(`[${subject}]:`)
  console.log(info_html)
  axios.post(log_webhook_url, {
    attachment: {
      fallback: `${subject}:${info_html.slice(0, 50)}`,
      title: subject,
      text: info_html,
      color: "#FF0000",
      pretext: ``,
      fields: []
    }
  }, {
    headers: {
      "Content-Type": "application/json"
    }
  }).then(axresp => { }).catch(axerr => { })
}

/**
 * @returns {Promise<>}
 * @param {string} log_webhook_url
 * @param {String} dir_fullpath 
 * @param {Number} size_limit_mb 
 */
function uploadablify(dir_fullpath, size_limit_mb, log_webhook_url) {
  return new Promise(async resolve => {
    let o_list = await Toolbox.safeListAllInDir(dir_fullpath);
    let o_toobig_files = o_list.filter(e => e.stats.isFile()
      && e.stats.size > size_limit_mb * 1024 * 1024)
    // debugger

    /**
     * @returns {Promise<{ok:Boolean}>}
     * @param {String} full_path 
     * @param {String} distRarFullPath
     */
    let ProcessingAsNormalFileOrDir = function (full_path, distRarFullPath = "") {
      return new Promise(async resolve_pan => {
        let parsedp = path.parse(full_path);
        let o_stats = await Toolbox.getStats(full_path);
        if (!o_stats.ok) {
          return resolve({
            ok: false,
            msg: `无法获取stats of ${full_path}:${o_stats.msg}`
          })
        }
        /**@type {string[]} */
        let files_in = [];
        if (o_stats.stats.isFile()) {
          files_in = [full_path];
        } else {
          let o_list = await Toolbox.safeListDir(full_path);
          files_in = o_list.map(e => e.full_path)
        }
        if (!distRarFullPath) {
          distRarFullPath = path.join(parsedp.dir, `(rared)${parsedp.base}.rar`)
        }
        let o_packRar = await rarPack(files_in,
          distRarFullPath, size_limit_mb);//防止原本的partx文件和新的part文件路径完全重合造成bug
        if (!o_packRar.ok) {
          await logToWebhook(`打包RAR失败`,
            `fullpath=${full_path}\n
            \n reason = :
            \n${o_packRar.msg}`, log_webhook_url);
          return resolve_pan({
            ok: false
          })
        }
        let o_testRar = await rarTest(o_packRar.data.rarfile_realpath);
        if (!o_testRar.ok) {
          await logToWebhook(`测试RAR文件失败`,
            `fullpath=${full_path}\n
          \n reason = :
          \n${o_testRar.msg}`, log_webhook_url);
          return resolve_pan({
            ok: false
          })
        }
        await new Promise(r => {
          del(full_path).then(async err => {
            if (err.err_msg) {
              await logToWebhook(`删除文件失败`,
                `fullpath=${full_path}\n
            \n reason = :
            \n${err.err_msg}`, log_webhook_url);
            }

            r();
          })
        });
        return resolve_pan({
          ok: true
        })
      })
    };

    /**
     * @return {Promise<{ok:Boolean}>}
     * @param {String} full_path 
     */
    let ProcessingAsRarFile = function (full_path) {
      /**
       * @description 基本思路
       * 分别处理part[0]*1文件和其他part
       * 如果是第一个part,需要解压到一个文件夹,然后删除所有相同数字个数的其他part文件
       * 如果是不以partxx.rar结尾的,需要解压到一个文件夹,然后删除这个rar文件
       * 然后重新打包这个文件夹（就像是个普通文件）
       * 如果不是第一个part,首先要检查一下是否文件还存在
       * 如果不存在了,说明已经在part1的过程中处理了
       * 如果还存在,就当成普通文件处理
       */
      return new Promise(async resolve_par => {
        let parsed_p = path.parse(full_path);
        if (full_path.search(/part[0-9]+\.rar$/) >= 0) {
          let is_part1 = full_path.search(/part[0]*1\.rar$/) >= 0;
          if (!is_part1) {
            let o_exist = await Toolbox.checkExist(full_path);
            if (!o_exist) {
              return resolve_par({ ok: true });
            }
          }

          if (true) {
            let dist_dir = path.join(parsed_p.dir, `${
              parsed_p.name.replace(/part[0]*1$/, "")
              }`)
            if (dist_dir.endsWith(".") && path.parse(dist_dir).ext == ".") {
              dist_dir = dist_dir.replace(/\.$/, "");
            }
            if (dist_dir == parsed_p.dir) {
              dist_dir = path.join(parsed_p.dir, "hujimiya_unnamed." + Date.now());
            }
            let o_unpackWith7z = await unpackWith7z(full_path, dist_dir);
            if (!o_unpackWith7z.ok) {
              await logToWebhook(`用7z解压文件失败`,
                `fullpath=${full_path}\n
          \n reason = :
          \n${o_unpackWith7z.msg}`, log_webhook_url);
              return resolve_par({
                ok: false
              })
            }
            for (let ivf of o_unpackWith7z.data.involved_files) {
              await new Promise(r => del(ivf)
                .then(async err => {
                  if (err.err_msg) {
                    await logToWebhook(`7z解压成功后删除RAR文件失败`,
                      `fullpath=${full_path}\n
            \n reason = :
            \n${err.err_msg}`, log_webhook_url);
                  }

                  // debugger
                  r();
                })
              )
            }
            // debugger
            let dist_dir_name = path.parse(dist_dir).name;
            let o_process = await ProcessingAsNormalFileOrDir(dist_dir,
              path.join(parsed_p.dir, `(Rared)${dist_dir_name}`, `${dist_dir_name}.rar`)
            );
            return resolve_par({
              ok: o_process.ok
            })
          }
        } else {
          /**@description 作为没有分卷的rar文件 */
          // debugger
          let dist_dirpath = path.join(parsed_p.dir, parsed_p.name)
          let o_unpack = await unrar(full_path,
            dist_dirpath);
          if (!o_unpack.ok) {
            await logToWebhook(`WinRAR解压文件失败`,
              `fullpath=${full_path}\n
      \n reason = :
      \n${o_unpack.msg}`, log_webhook_url);
            return resolve_par({
              ok: false
            })
          }
          await new Promise(r => del(full_path).then(async err => {
            if (err.err_msg) {
              await logToWebhook(`WinRAR解压成功后删除文件失败`,
                `fullpath=${full_path}\n
      \n reason = 
      \n${err.err_msg}`, log_webhook_url);
            }
            r();
          }));
          let o_process = await ProcessingAsNormalFileOrDir(dist_dirpath);
          return resolve_par({
            ok: o_process.ok
          })
        }
        // resolve_par()
        debugger
        console.log("不该运行来这里")
      })
    }

    let normal_files = o_toobig_files.filter(e => !e.full_path.endsWith(".rar"));
    let rar_files = o_toobig_files.filter(e => e.full_path.endsWith(".rar")).sort();
    for (let nmfile of normal_files) {
      await ProcessingAsNormalFileOrDir(nmfile.full_path)
    }
    for (let rarfile of rar_files) {
      await ProcessingAsRarFile(rarfile.full_path)
    }
    resolve();

  })
}

/**
 * @description 必须完全打包！然后生成一个内含文件列表的文本记录
 * @returns {Promise<>}
 * @param {string} log_webhook_url
 * @param {String} dir_fullpath 
 * @param {Number} size_limit_mb 
 */
function uploadablify_kd_dir(dir_fullpath, log_webhook_url) {
  let size_limit_mb = 990;
  return new Promise(async resolve => {
    let o_tree = await TreeCli({
      base: dir_fullpath,
      noreport: false,
      l: 8//深入程度
    });
    debugger
    //o_tree.report
    let simple_path = path.basename(dir_fullpath + "-pack.rar");
    let rar_path = path.join(dir_fullpath, simple_path);
    let password = "savemyfiles65"
    let o_pack = await rarPackPlusPassword([dir_fullpath], rar_path, size_limit_mb, password);
    if (!o_pack.ok) {
      console.log("打包失败！" + o_pack.msg);
      return resolve()
    }
    let o_test = await rarTestPlusPassword(o_pack.data.rarfile_realpath, password)
    if (!o_test.ok) {
      console.log("测试失败!" + o_test.msg);
    }
    let CommentFile = path.join(dir_fullpath, `PackedFileList.fl`);
    let o_write = await fs.writeFile(CommentFile, `压缩包密码是：${password}\r\n压缩包内文件列表是\r\n${o_tree.report}`);
    debugger
    resolve();

  })
}

/**
 * @description 必须完全打包！然后生成一个内含文件列表的文本记录
 * @returns {Promise<>}
 * @param {string} log_webhook_url
 * @param {String} dir_fullpath 
 * @param {Number} size_limit_mb 
 */
function uploadablify_kd_dirVerEach(dir_fullpath, log_webhook_url) {
  let size_limit_mb = 985;
  return new Promise(async resolve => {
    let o_tree = await TreeCli({
      base: dir_fullpath,
      noreport: false,
      l: 8//深入程度
    });
    let CONST_password = "savemyfiles65"
    let o_list = await Toolbox.safeListDir(dir_fullpath);
    if (o_list.length) {
      for (let item of o_list) {
        let simple_path = path.basename(item.relative_path) + "-EachPack.rar"
        // debugger
        let rar_path = path.join(dir_fullpath, simple_path)

        let o_pack = await rarPackPlusPassword([item.full_path], rar_path, size_limit_mb, CONST_password);
        if (!o_pack.ok) {
          console.log("打包失败了：", item.full_path)
          continue;
        }
        let o_test = await rarTestPlusPassword(o_pack.data.rarfile_realpath, CONST_password);
        if (!o_test.ok) {
          console.log("测试失败!" + o_test.msg);
        }

        // debugger
      }
    }
    debugger
    //o_tree.report
    let CommentFile = path.join(dir_fullpath, `PackedFileList.fl`);
    let o_write = await fs.writeFile(CommentFile, `压缩包密码是：${CONST_password}\r\n压缩包内文件列表是\r\n${o_tree.report}`);
    debugger
    resolve();

  })
}

// if (!module.parent) {
//   // uploadablify_kd_dirVerEach('V:\\广州市疫情新闻发布')
// }


module.exports = {
  rarPack,
  unrar,
  uploadablify,
  uploadablify_kd_dir,
  uploadablify_kd_dirVerEach,
  rarTest,
  unpackWith7z,
  listWith7z,
  extractOneFileWith7z
}